home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / unix / c / stat < prev    next >
Text File  |  1996-11-09  |  5KB  |  214 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/stat,v $
  4.  * $Date: 1996/10/30 22:04:51 $
  5.  * $Revision: 1.5 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: stat,v $
  10.  * Revision 1.5  1996/10/30 22:04:51  unixlib
  11.  * Massive changes made by Nick Burret and Peter Burwood.
  12.  *
  13.  * Revision 1.4  1996/09/16 21:23:52  unixlib
  14.  * CL_0002 Nick Burret
  15.  * Minor changes to file handling
  16.  * Change most error numbers, and use in assembler sources (SJC)
  17.  * Various minor bug fixes and compatability changes.
  18.  *
  19.  * Revision 1.3  1996/07/21 22:12:31  unixlib
  20.  * CL_0001 Nick Burret
  21.  * Improve memory handling. Remove C++ library incompatibilities.
  22.  * Improve file stat routines.
  23.  *
  24.  * Revision 1.2  1996/05/06 09:01:35  unixlib
  25.  * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
  26.  * Saved for 3.7a release.
  27.  *
  28.  * Revision 1.1  1996/04/19 21:35:27  simon
  29.  * Initial revision
  30.  *
  31.  ***************************************************************************/
  32.  
  33. static const char rcs_id[] = "$Id: stat,v 1.5 1996/10/30 22:04:51 unixlib Rel $";
  34.  
  35. #include <errno.h>
  36. #include <time.h>
  37. #include <fcntl.h>
  38. #include <stdio.h>
  39. #include <unistd.h>
  40.  
  41. #include <sys/types.h>
  42. #include <sys/dev.h>
  43. #include <sys/unix.h>
  44. #include <sys/stat.h>
  45. #include <sys/os.h>
  46. #include <sys/swis.h>
  47.  
  48. static void __stat (register int *, register struct stat *);
  49.  
  50. int
  51. stat (const char *fname, struct stat *buf)
  52. {
  53.   int r[6];
  54.   _kernel_oserror *e;
  55.   char *file;
  56.  
  57.   if (!buf)
  58.     {
  59.       errno = EINVAL;
  60.       return (-1);
  61.     }
  62.  
  63.   file = __uname ((char *)fname, 0);
  64.  
  65.   if (e = os_file (0x05, file, r))
  66.     {
  67.       __seterr (e);
  68.       return (-1);
  69.     }
  70.   if (!r[0])
  71.     {
  72.       errno = ENOENT;
  73.       return (-1);
  74.     }
  75.  
  76.   buf->st_dev = makedev (DEV_RISCOS, 0);
  77.  
  78.   __stat (r, buf);
  79.  
  80.   return (0);
  81. }
  82.  
  83. int
  84. lstat (const char *fname, struct stat *buf)
  85. {
  86.   return stat (fname, buf);
  87. }
  88.  
  89. int
  90. fstat (int fd, struct stat *buf)
  91. {
  92.   register struct file *f;
  93.  
  94.   if (!buf)
  95.     {
  96.       errno = EINVAL;
  97.       return (-1);
  98.     }
  99.  
  100.   if (BADF (fd))
  101.     {
  102.       errno = EBADF;
  103.       return (-1);
  104.     }
  105.  
  106.   f = __u->file + fd;
  107.  
  108.   buf->st_dev = f->dev;
  109.  
  110.   __stat (f->r, buf);
  111.  
  112.   return (0);
  113. }
  114.  
  115. /* This function is used by __stat() and readdir().  */
  116.  
  117. unsigned int
  118. __get_file_serial_no (char *fname)
  119. {
  120.   int r[10];
  121.   char tmp[256], *s;
  122.   unsigned int ino;
  123.   char *name;
  124.  
  125.   /* The file serial number, which distringuishes this file from
  126.      all other files on the same device.
  127.  
  128.      Hash the filename to hopefully make a fairly unique number.  */
  129.  
  130.   name = __uname (fname, 0);
  131.  
  132.   r[0] = 37;
  133.   r[1] = (int)name;
  134.   r[2] = (int)tmp;
  135.   r[3] = r[4] = 0;
  136.   r[5] = 255;
  137.   ino = r[3] + r[4];
  138.   if (!os_swi (OS_FSControl, r) && r[5] >= 0)
  139.     {
  140.       for (s = tmp; s[0] || s[1]; s += 2)
  141.         ino += (s[1] == 0) ? s[0]<<5 : s[0] * s[1];
  142.     }
  143.   return ino;
  144. }
  145.  
  146. static void
  147. __stat (register int *r, register struct stat *buf)
  148. {
  149.   buf->st_ino = __get_file_serial_no ((char *)r[1]);
  150.  
  151.   buf->st_mode = ((r[5] & 0001) << 8) | ((r[5] & 0002) << 6) |
  152.     ((r[5] & 0020) >> 2) | ((r[5] & 0040) >> 4);
  153.  
  154.   switch (r[0])
  155.     {
  156.     case 1:
  157.       buf->st_mode |= S_IFREG;
  158.       break;
  159.     case 2:            /* Normal directory */
  160.       buf->st_mode |= S_IFDIR | 0700;    /* FS bug */
  161.       break;
  162.     case 3:            /* Image directory (RISC OS 3 and above) */
  163.       buf->st_mode |= S_IFDIR | ((buf->st_mode & 0400) >> 2);    /* FS bug */
  164.       break;
  165.     }
  166.  
  167.   switch (major (buf->st_dev))
  168.     {
  169.     case DEV_TTY:
  170.       buf->st_mode |= S_IFCHR;
  171.       break;
  172.     case DEV_PIPE:
  173.       buf->st_mode |= 0;
  174.       break;
  175.     }
  176.  
  177.   /* The number of hard links to the file. For RISC OS, there is only
  178.      one hard link since only one directory can point to the file.
  179.      Symbolic links are not counted in the total.  */
  180.   buf->st_nlink = 1;
  181.   buf->st_uid = 1;
  182.   buf->st_gid = 1;
  183.   buf->st_rdev = 0;
  184.   buf->st_size = r[4];
  185.   /* Disc space that the file occupies, measured in units of 512
  186.      byte blocks.  */
  187.   buf->st_nblocks = r[4] / 512;
  188.   /* Optimal block size for reading or writing this file, in bytes.
  189.      Since sector sizes are usually 512 or 1024 bytes on RISC OS
  190.      disc formats, we'll safely assume a block size of 1024.  */
  191.   buf->st_blksize = 1024;
  192.  
  193.   if ((((unsigned int) r[2]) >> 20) == 0xfff)    /* date stamped file */
  194.     {
  195.       register unsigned int t1, t2, tc;
  196.  
  197.       t1 = (unsigned int) (r[3]);
  198.       t2 = (unsigned int) (r[2] & 0xff);
  199.  
  200.       tc = 0x6e996a00U;
  201.       if (t1 < tc)
  202.     t2--;
  203.       t1 -= tc;
  204.       t2 -= 0x33;        /* 00:00:00 Jan. 1 1970 = 0x336e996a00 */
  205.  
  206.       t1 = (t1 / 100) + (t2 * 42949673U);    /* 0x100000000 / 100 = 42949672.96 */
  207.       t1 -= (t2 / 25);        /* compensate for .04 error */
  208.  
  209.       buf->st_atime = buf->st_mtime = buf->st_ctime = t1;
  210.     }
  211.   else
  212.     buf->st_atime = buf->st_mtime = buf->st_ctime = 0;
  213. }
  214.